package com.lzb.randomturntable.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;

import androidx.annotation.Nullable;

import com.blankj.utilcode.util.SizeUtils;
import com.lzb.basic.utils.SPUtil;
import com.lzb.randomturntable.Content;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Desc: 幸运转盘控件
 */
public class TurnTableView extends View {

    private static final int DEF_SIZE = SizeUtils.dp2px(100);
    private Paint mPaint;
    private Adapter mAdapter;
    //上次动画旋转到的角度
    private float preToDegrees = 0;
    //当前是否正在转动中
    private boolean isRotateNow = false;

    public TurnTableView(Context context) {
        this(context, null);
    }

    public TurnTableView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    public void setTextSize(float textSize) {
        mPaint.setTextSize(textSize);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        //转盘一般都为圆形，所以它的长宽是一样的，下面将长宽处理为相同的值
        if (width > 0 && height > 0) {
            width = height = Math.min(width, height);
        } else {
            width = height = Math.max(width, height);
            if (width <= 0) {
                width = height = DEF_SIZE;
            }
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawItem(canvas);
    }

    private void drawItem(Canvas canvas) {
        Adapter adapter = mAdapter;
        if (adapter == null) return;
        if (adapter.getItemCount() <= 0) return;
        float oneArcAngle = 360f / adapter.getItemCount();
        float startAngle = -oneArcAngle / 2 - 90;//第一个从正上方开始
        RectF rectF = new RectF();
        rectF.left = getPaddingLeft();
        rectF.top = getPaddingTop();
        rectF.right = getWidth() - getPaddingRight();
        rectF.bottom = getHeight() - getPaddingBottom();

        for (int i = 0; i < adapter.getItemCount(); i++) {
            adapter.onDrawItem(canvas, rectF, startAngle, oneArcAngle, mPaint, i);
            startAngle += oneArcAngle;
        }
    }

    public void setAdapter(Adapter adapter) {
        mAdapter = adapter;
        adapter.setObserver(observer);
        invalidate();
    }

    public Adapter getAdapter() {
        return mAdapter;
    }

    public void startRotate() {
        if (isRotateNow) {
            return;
        }
        isRotateNow = true;
        startAnimation(createAnimation());
    }

    private Animation createAnimation() {
        float randomDegrees = new Random().nextFloat() * 360;
        float toDegrees = 10 * 360 + randomDegrees;
        RotateAnimation rotateAnimation = new RotateAnimation(preToDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        preToDegrees = randomDegrees;
        //动画结束后，保留显示在结束时的画面
        rotateAnimation.setFillAfter(true);
        long duration = SPUtil.getInt(getContext(), Content.rotateDuration, 1) * 1000L;
        rotateAnimation.setDuration(duration);
        rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                if (listener != null) listener.onRotateStart();
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (listener != null) listener.onRotateEnd();
                Adapter adapter = mAdapter;
                if (adapter == null) return;

                float tmpRotateDegrees = 360 - randomDegrees;
                float oneArcAngle = 360f / adapter.getItemCount();
                int pos = (int) ((tmpRotateDegrees + oneArcAngle / 2) / oneArcAngle);
                if (pos >= adapter.getItemCount()) {
                    pos = 0;
                }
                if (listener != null) {
                    listener.onSelItem(pos);
                }
                isRotateNow = false;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        return rotateAnimation;
    }

    private Observer observer = new Observer() {
        @Override
        public void onDataChanged() {
            postInvalidate();
        }
    };

    interface Observer {

        void onDataChanged();

    }

    public abstract static class Adapter<T> {

        private List<T> dataList;
        private Observer observer;

        void setObserver(Observer observer) {
            this.observer = observer;
        }

        void notifyDataChanged() {
            if (observer != null) {
                observer.onDataChanged();
            }
        }

        public void setDataList(List<T> dataList) {
            this.dataList = dataList;
            notifyDataChanged();
        }

        public void addItem(T item) {
            if (dataList == null) {
                dataList = new ArrayList<>();
            }
            dataList.add(item);
            notifyDataChanged();
        }

        public void removeItem(T item) {
            if (dataList == null) return;
            if (dataList.contains(item)) {
                dataList.remove(item);
                notifyDataChanged();
            }
        }

        public int getItemCount() {
            return dataList == null ? 0 : dataList.size();
        }

        public T getItem(int pos) {
            if (dataList == null) {
                return null;
            }
            if (pos < 0 || pos >= dataList.size()) {
                return null;
            }
            return dataList.get(pos);
        }

        /**
         * @param canvas
         * @param oval
         * @param startAngle
         * @param sweepAngle
         * @param paint
         * @param itemPos    数据元素在数据列表中的位置
         */
        protected abstract void onDrawItem(Canvas canvas, RectF oval, float startAngle, float sweepAngle, Paint paint, int itemPos);

    }

    private IListener listener;

    public void setListener(IListener listener) {
        this.listener = listener;
    }

    /**
     * 监听器
     */
    public interface IListener {

        /**
         * 旋转开始回调方法
         */
        void onRotateStart();

        /**
         * 旋转结束回调方法
         */
        void onRotateEnd();

        /**
         * 旋转结束后，指针所指向的选项
         *
         * @param pos 指针所指向的选项位置
         */
        void onSelItem(int pos);

    }

}
